<template>
  <el-select v-model="selectValue" v-bind="$attrs" :value-key="valueKey" :multiple="multiple" @change="handleChange" @clear="handleClear">
    <el-option
      v-for="item in optionsList"
      :key="getOptionKey(item)"
      :label="getOptionLabel(item)"
      :value="getOptionValue(item)"
      :disabled="getOptionDisabled(item)"
    />
    <el-option
      v-if="showEmptyOption"
      :key="emptyOption.value"
      :label="emptyOption.label"
      :value="emptyOption.value"
      :disabled="emptyOption.disabled"
    />
  </el-select>
</template>

<script setup lang="ts">
  import { ref, computed, watch, defineEmits, defineProps, useAttrs } from 'vue'
  defineOptions({ name: 'SelectList' })
  // 选项数据类型
  interface OptionItem {
    [key: string]: any
    id?: string | number
    label?: string
    value?: string | number
    disabled?: boolean
  }

  // 空值选项配置
  interface EmptyOption {
    label: string
    value: any
    disabled?: boolean
  }

  // 组件Props类型
  interface SelectListProps {
    /** 绑定值 */
    modelValue: any
    /** 选项数据 */
    options: OptionItem[]
    /** 是否多选 */
    multiple?: boolean
    /** 选项的值键名 */
    valueKey?: string
    /** 选项的标签键名 */
    labelKey?: string
    /** 选项的禁用键名 */
    disabledKey?: string
    /** 选项的唯一标识键名 */
    keyField?: string
    /** 空值选项配置 */
    emptyOption?: EmptyOption | null
    /** 是否显示空值选项 */
    showEmptyOption?: boolean
  }

  // Props定义
  const props = withDefaults(defineProps<SelectListProps>(), {
    multiple: false,
    valueKey: 'id',
    labelKey: 'label',
    disabledKey: 'disabled',
    keyField: 'id',
    emptyOption: null,
    showEmptyOption: false,
  })

  // Emits定义
  const emit = defineEmits<{
    'update:modelValue': [value: any]
    change: [value: any, option?: OptionItem | OptionItem[]]
    clear: []
  }>()

  // 获取透传属性（排除已定义的props）
  const attrs = useAttrs()

  // 内部值管理
  const selectValue = ref<any>()

  // 处理选项列表
  const optionsList = computed(() => {
    return Array.isArray(props.options) ? props.options : []
  })

  // 获取选项的键
  const getOptionKey = (item: OptionItem): string | number => {
    return item[props.keyField] ?? item[props.valueKey] ?? item.id ?? ''
  }

  // 获取选项的标签
  const getOptionLabel = (item: OptionItem): string => {
    return item[props.labelKey] ?? item.label ?? item.name ?? String(item[props.valueKey] ?? '')
  }

  // 获取选项的值
  const getOptionValue = (item: OptionItem): any => {
    return item[props.valueKey] ?? item.value ?? item.id
  }

  // 获取选项的禁用状态
  const getOptionDisabled = (item: OptionItem): boolean => {
    return item[props.disabledKey] ?? item.disabled ?? false
  }

  // 根据ID查找选项
  const findOptionById = (id: any): OptionItem | undefined => {
    return optionsList.value.find((item) => getOptionValue(item) === id)
  }

  // 根据ID数组查找选项
  const findOptionsByIds = (ids: any[]): OptionItem[] => {
    return ids.map((id) => findOptionById(id)).filter(Boolean) as OptionItem[]
  }

  // 初始化回显值
  const initDisplayValue = () => {
    if (props.modelValue == null) {
      selectValue.value = props.multiple ? [] : undefined
      return
    }

    if (props.multiple) {
      // 多选模式：根据ID数组找到对应的选项对象
      const ids = Array.isArray(props.modelValue) ? props.modelValue : [props.modelValue]
      const foundOptions = findOptionsByIds(ids)
      selectValue.value = foundOptions
    } else {
      // 单选模式：根据ID找到对应的选项对象
      const foundOption = findOptionById(props.modelValue)
      selectValue.value = foundOption || props.modelValue
    }
  }

  // 监听modelValue变化，更新显示值
  watch(
    () => props.modelValue,
    () => {
      initDisplayValue()
    },
    { immediate: true },
  )

  // 监听options变化，重新初始化显示值
  watch(
    () => props.options,
    () => {
      initDisplayValue()
    },
    { deep: true },
  )

  // 处理值变化
  const handleChange = (value: any) => {
    let emitValue: any

    if (props.multiple) {
      // 多选模式：提取选中项的ID
      emitValue = Array.isArray(value) ? value.map((item) => getOptionValue(item)) : []
      emit('change', emitValue, value)
    } else {
      // 单选模式：提取选中项的ID
      emitValue = value ? getOptionValue(value) : value
      const option = value ? value : undefined
      emit('change', emitValue, option)
    }

    emit('update:modelValue', emitValue)
  }

  // 处理清空
  const handleClear = () => {
    const emptyValue = props.multiple ? [] : undefined
    selectValue.value = emptyValue
    emit('update:modelValue', emptyValue)
    emit('clear')
  }

  // 获取当前选中的完整选项数据
  const getSelectedOptions = (): OptionItem | OptionItem[] | undefined => {
    if (props.modelValue == null) {
      return props.multiple ? [] : undefined
    }

    if (props.multiple) {
      const ids = Array.isArray(props.modelValue) ? props.modelValue : [props.modelValue]
      return findOptionsByIds(ids)
    } else {
      return findOptionById(props.modelValue)
    }
  }

  // 暴露方法给父组件
  defineExpose({
    getSelectedOptions,
    findOptionById,
    findOptionsByIds,
  })
</script>
